package org.sundatagroup.aurora.core.service.querier;

import java.util.HashMap;
import java.util.HashSet;

import org.springframework.stereotype.Component;

import com.google.gson.JsonElement;

/**
 * <p>通用查询服务中心, 接收所有查询服务的注册, 并能将查询请求发送到指定的服务等
 * </p>
 * 
 * @author Zdream
 * @date 2018-05-30
 * @since 0.2.0
 */
@Component
public class QuerierCenter {

	/**
	 * 服务集
	 * <br>type - querier
	 */
	HashMap<String, IQuerier> queriers = new HashMap<>();
	
	/**
	 * 请求集 (白名单)
	 * <br>id - set&lt;type&gt;
	 */
	HashMap<String, HashSet<String>> requests = new HashMap<>();

	/**
	 * 注册
	 * @param querier
	 *   查询服务
	 */
	public void register(IQuerier querier) {
		if (querier == null) {
			throw new NullPointerException("查询服务 querier = null");
		}
		
		String[] types = querier.types();
		for (int i = 0; i < types.length; i++) {
			String type = types[i];
			queriers.put(type, querier);
		}
	}
	
	/**
	 * 允许指定请求者能够调用的服务
	 * @param id
	 *   请求者 id, 用于限定权限
	 * @param types
	 *   允许的类别
	 */
	public void permit(String id, String... types) {
		if (id == null) {
			throw new NullPointerException("请求者 id = null");
		}
		
		HashSet<String> set = requests.get(id);
		if (set == null) {
			set = new HashSet<>();
			requests.put(id, set);
		}
		for (int i = 0; i < types.length; i++) {
			String type = types[i];
			set.add(type);
		}
	}
	
	/**
	 * 查询
	 * @param id
	 *   请求者 id, 用于限定权限
	 * @param type
	 *   类别
	 * @param key
	 *   参数
	 * @return
	 *   查询结果, null 或 Json Array 也是可能的
	 */
	public JsonElement query(String id, String type, JsonElement key) {
		if (type == null) {
			throw new NullPointerException("查询类别 type = null");
		}
		if (id == null) {
			throw new NullPointerException("请求者 id = null");
		}
		
		// 检查权限步骤
		HashSet<String> set = requests.get(id);
		if (set == null || !set.contains(type)) {
			return null; // 确定没有权限
		}
		
		// 查询步骤
		IQuerier querier = queriers.get(type);
		if (querier == null) {
			return null;
		}

		JsonElement e = querier.query(type, key);
		if (e.isJsonNull()) {
			return null;
		}
		
		return e;
	}

}
